﻿using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Fwql.Net.Utils;

namespace Fwql.Net.Extensions
{
    public static class DictionaryExtension
    {
        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue> Sort<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
        {
            Guard.NotNull(dictionary, "dictionary");

            return new SortedDictionary<TKey, TValue>(dictionary);
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dictionary"></param>
        /// <param name="comparer"></param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue> Sort<TKey, TValue>(this IDictionary<TKey, TValue> dictionary,
                                                                   IComparer<TKey> comparer)
        {
            Guard.NotNull(dictionary, "dictionary");
            Guard.NotNull(comparer, "comparer");

            return new SortedDictionary<TKey, TValue>(dictionary, comparer);
        }

        /// <summary>
        /// 排序
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static IDictionary<TKey, TValue> SortByValue<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
        {
            return
                (new SortedDictionary<TKey, TValue>(dictionary)).OrderBy(kvp => kvp.Value).ToDictionary(
                    item => item.Key, item => item.Value);
        }

        /// <summary>
        /// 健值互调
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static IDictionary<TValue, TKey> Invert<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
        {
            Guard.NotNull(dictionary, "dictionary");
            return dictionary.ToDictionary(pair => pair.Value, pair => pair.Key);
        }

        /// <summary>
        /// Merges the specified instance.
        /// </summary>
        /// <param name="instance">The instance.</param>
        /// <param name="from">From.</param>
        /// <param name="replaceExisting">if set to <c>true</c> [replace existing].</param>
        public static void Merge<TKey, TValue>(this IDictionary<TKey, TValue> instance, IDictionary<TKey, TValue> from,
                                               bool replaceExisting)
        {
            Guard.NotNull(instance, "instance");
            Guard.NotNull(from, "from");

            foreach (var pair in from)
            {
                if (!replaceExisting && instance.ContainsKey(pair.Key))
                {
                    continue; // Try the next
                }

                instance[pair.Key] = pair.Value;
            }
        }

        /// <summary>
        /// 转HashTable
        /// </summary>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="dictionary"></param>
        /// <returns></returns>
        public static Hashtable ToHashTable<TKey, TValue>(this IDictionary<TKey, TValue> dictionary)
        {
            Guard.NotNull(dictionary, "dictionary");
            var table = new Hashtable();
            foreach (var item in dictionary)
                table.Add(item.Key, item.Value);

            return table;
        }

        /// <summary>
        /// Appends the specified value on the existing value
        /// </summary>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="separator"></param>
        /// <param name="value"></param>
        public static void AppendValue(this IDictionary<string, string> dictionary, string key, string separator,
                                       string value)
        {
            Guard.NotNull(dictionary, "dictionary");
            Guard.NotEmpty(key, "key");
            Guard.NotEmpty(separator, "separator");
            Guard.NotNull(value, "value");

            dictionary[key] = dictionary.ContainsKey(key) ? dictionary[key].Append(separator, value) : value;
        }

        /// <summary>
        /// Appends the specified value at the beginning of the existing value
        /// </summary>
        /// <param name="dictionary"></param>
        /// <param name="key"></param>
        /// <param name="separator"></param>
        /// <param name="value"></param>
        public static void PrependValue(this IDictionary<string, string> dictionary, string key, string separator,
                                        string value)
        {
            Guard.NotNull(dictionary, "dictionary");
            Guard.NotEmpty(key, "key");
            Guard.NotEmpty(separator, "separator");
            Guard.NotNull(value, "value");

            dictionary[key] = dictionary.ContainsKey(key) ? value.Append(separator, dictionary[key]) : value;
        }
    }
}